Blog

Bing maps API integration with dynamics 365 CRM

23 May 2021
Blog Image
LEARN HOW TO IMPLEMENT DISTANCE CALCULATION

In our previous blog, we helped you with the integration of Bing Maps API with Dynamics 365 CRM application and creation of Auto Suggestion functionality on the address field. With this blog, we will guide you on how to calculate the distance between a source and the destination address.

Distance Calculation from Source to Destination Address Field into Dynamics 365 CRM

Step 1: Create a web resource name it as Source Web Resource and place all the above code into it. Our Source Web resource will remain the same and will not change.

Step 2: Create another web resource and name it as Destination Web Resource and place the below code:

<html>
<head>
<title>
autosuggestuiwithoutmapHTML</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<style type="text/css">
body { margin: 0; padding: 0; overflow: hidden; font-family: 'Segoe UI', Helvetica, Arial, Sans-Serif } </style>
</head>
<body style="overflow-wrap: break-word;" onfocusout="parent.setEmailRange();">
<div id="searchBoxContainer">
<label style="display: inline-block; max-width: 100%;margin-bottom: 5px;font-weight: bold;color: #666;" for="Search">
To Address</label>
<br>
<input id="searchBox" style="display: block;width: 450px;height: 35px;font-size: 15px;line-height: 1.42857;&#10;        color: rgb(85, 85, 85);background-color: rgb(255, 255, 255);background-image: none;&#10;        border: 1px solid rgb(204, 204, 204);border-radius: 0px;box-shadow: rgba(0, 0, 0, 0.075) 0px 1px 1px inset;&#10;        transition: border-color 0.15s ease-in-out 0s, box-shadow 0.15s ease-in-out 0s;box-sizing:content-box;/* padding: 10px; */padding-left: 12px;" type="text" placeholder="Search your address here…" autocomplete="off">
</div>
<script type="text/javascript">
function setClientApiContext(formContext) { // Optionally set Xrm and formContext as global variables on the page. window._formContext = formContext; } function loadMapScenario() { Microsoft.Maps.loadModule('Microsoft.Maps.AutoSuggest', { callback: onLoad, errorCallback: onError }); function onLoad() { var options = { maxResults: 5 }; var manager = new Microsoft.Maps.AutosuggestManager(options); manager.attachAutosuggest('#searchBox', '#searchBoxContainer', selectedSuggestion); } function onError(message) { document.getElementById('printoutPanel').innerHTML = message; } function selectedSuggestion(suggestionResult) { _formContext.getAttribute("crm-deststreet").setValue(suggestionResult.address.addressLine); _formContext.getAttribute("crm-destcity").setValue(suggestionResult.address.locality); _formContext.getAttribute("crm-destpostalcode").setValue(suggestionResult.address.postalCode); _formContext.getAttribute("crm-deststateorprovince").setValue(suggestionResult.address.adminDistrict); _formContext.getAttribute("crm-destcountry").setValue(suggestionResult.address.countryRegion); var concatDestinationAddress = suggestionResult.address.addressLine + ',' + suggestionResult.address.locality + ',' + suggestionResult.address.adminDistrict + ',' + suggestionResult.address.countryRegion; var sourceAddressLine = _formContext.getAttribute("crm-srcstreet").getValue(); var sourceAddressCity = _formContext.getAttribute("crm-srccity").getValue(); var sourceAddressState = _formContext.getAttribute("crm-srcstate").getValue(); var sourceAddressCountry = _formContext.getAttribute("crm-srccountry ").getValue(); var concatSourceAddress = sourceAddressLine + ',' + sourceAddressCity + ',' + sourceAddressState + ',' + sourceAddressCountry; map = new Microsoft.Maps.Map('#myMap', {}); //Load the directions module. Microsoft.Maps.loadModule('Microsoft.Maps.Directions', function () { //Create an instance of the directions manager. directionsManager = new Microsoft.Maps.Directions.DirectionsManager(map); //Create waypoints to route between. var sourceWayPoint = new Microsoft.Maps.Directions.Waypoint({ address: concatSourceAddress }); directionsManager.addWaypoint(sourceWayPoint); var destinationWayPoint = new Microsoft.Maps.Directions.Waypoint({ address: concatDestinationAddress }); directionsManager.addWaypoint(destinationWayPoint); //Add event handlers to directions manager. Microsoft.Maps.Events.addHandler(directionsManager, 'directionsError', directionsError); Microsoft.Maps.Events.addHandler(directionsManager, 'directionsUpdated', directionsUpdated); //Calculate directions. directionsManager.calculateDirections(); }); } function directionsUpdated(e) { //Get the current route index. var routeIdx = directionsManager.getRequestOptions().routeIndex; //Get the distance of the route, rounded to 2 decimal places. var distance = Math.round(e.routeSummary[routeIdx].distance * 100) / 100; //Get the distance units used to calculate the route. var units = directionsManager.getRequestOptions().distanceUnit; var distanceUnits = "; if (units == Microsoft.Maps.Directions.DistanceUnit.km) { distanceUnits = 'km' } else { //Must be in miles distanceUnits = 'miles' } } function directionsError(e) { alert('Error: ' + e.message + '\r\nResponse Code: ' + e.responseCode) } } </script>
<script src="https://www.bing.com/api/maps/mapcontrol?key={Your Bing Maps API Key} &amp;callback=loadMapScenario" defer="" type="text/javascript" async="">
</script>
<div id="myMap" style="position:relative;width:500px;height:500px;display:none;">
</div>
<div id="directionsItinerary">
</div>
</body>
</html>

Step 3: Almost all the above code is the same as explained earlier with some of the additions. Major additional code comes under selectedSuggestions function where we are getting source address field values into our destination address web resource and concatenating all the field values to form full address.

var concatSourceAddress = sourceAddressLine+’,’+sourceAddressCity+’,’+sourceAddressState+’,’+sourceAddressCountry;

Step 4: The most important step is where we are using Microsoft.Maps.Directions.DirectionsManager API and creating the object of it. Also, we are creating an object of Microsoft.Maps.Directions.Waypoint to provide sourceWaypoint and destinationWaypoint and pass our source address and destination address.

We are getting source address from CRM fields through the execution context while the destination address is from the (current) web resource autosuggestion address field.

Step 5: In the below section of the code, we are finally getting distance from the source to the destination address.

function directionsUpdated(e)

{

//Get the current route index.

var routeIdx = directionsManager.getRequestOptions().routeIndex;

//Get the distance of the route, rounded to 2 decimal places.

var distance = Math.round(e.routeSummary[routeIdx].distance * 100)/100;

//Get the distance units used to calculate the route.

var units = directionsManager.getRequestOptions().distanceUnit;

var distanceUnits = ”;

if (units == Microsoft.Maps.Directions.DistanceUnit.km)

{

distanceUnits = ‘km’

}

else

{

//Must be in miles

distanceUnits = ‘miles’

}

}

Here, we are creating a new function name directionsUpdated to get the shortest route index and distance using DirectionsManager.getRequestOptions AP. We can just display this distance using an alert field or store this value into the CRM Distance field by using _formContext global variable.

Provide Bing Maps API key in the highlighted section while keeping the rest of the code the same. It’s already been explained earlier in the blog.

Step 6: Similarly create JavaScript function to pass executioncontext object into our source as well as destination web resource created and place this Jscript function onload of that form.

Similarly, place both the web resources created into any entity form where you want distance functionality as shown above and finally Save and Publish.

Conclusion

In this blog, we went through the integration of Distance Calculation with just a few lines of code. Layering your CRM with Bing Maps will enable you to map your sales, accounts, leads, opportunities based on customer demographics lending you an unparalleled competitive edge in the market.